package sprites.interfaces;

import sprites.buildsprite.BuildSprite;

public interface IMobile
{

    /**
     * Returns the height of this sprite.
     */
    public abstract int getHeight ();


    /**
     * Attempts to move this sprite to specified <code>xs</code>,
     * <code>ys</code> location, if the sprite is right on specified location,
     * this method will return true.
     * <p>
     * 
     * For example :
     * 
     * <pre>
     *    Sprite s;
     *    public void update(long elapsedTime) {
     *       // move sprite to 100, 100 with speed 0.1 pixel in a millisecond
     *       if (s.moveTo(elapsedTime, 100, 100, 0.1) {
     *          // sprite has arrived to 100, 100
     *       }
     *    }
     * </pre>
     */
    public abstract boolean moveTo (long elapsedTime,
                                    double xs,
                                    double ys,
                                    double speed);


    /**
     * Moves this sprite as far as delta x (dx) and delta y (dy).
     */
    public abstract void move (double dx, double dy);


    /**
     * Moves sprite <code>x</code> coordinate as far as delta x (dx).
     */
    public abstract void moveX (double dx);


    /**
     * Moves sprite <code>y</code> coordinate as far as delta y (dy).
     */
    public abstract void moveY (double dy);


    /**
     * Forces sprite <code>x</code> position to specified coordinate.
     * <p>
     * 
     * The difference between {@link #setX(double)} with this method : <br>
     * <code>setX(double)</code> changes the sprite old position (oldX = xs),
     * while using <code>forceX(double)</code> <b>the old position is n ot
     * changed</b>.
     * <p>
     * 
     * This method is used on collision check to move the sprite, but still keep
     * the sprite old position value.
     */
    public abstract void forceX (double xs);


    /**
     * Forces sprite <code>y</code> position to specified coordinate.
     * <p>
     * 
     * The difference between {@link #setY(double)} with this method : <br>
     * <code>setY(double)</code> changes the sprite old position (oldY = ys),
     * while using <code>forceY(double)</code> <b>the old position is n ot
     * changed</b>.
     * <p>
     * 
     * This method is used on collision check to move the sprite, but still keep
     * the sprite old position value.
     */
    public abstract void forceY (double ys);


    /**
     * Returns sprite <code>x</code> coordinate.
     */
    public abstract double getX ();


    /**
     * Returns sprite <code>y</code> coordinate.
     */
    public abstract double getY ();


    /**
     * Returns sprite <code>x</code> coordinate before the sprite moving to
     * the current position.
     */
    public abstract double getOldX ();


    /**
     * Returns sprite <code>y</code> coordinate before the sprite moving to
     * the current position.
     */
    public abstract double getOldY ();


    /**
     * Accelerates sprite horizontal speed by <code>accel</code> and limit the
     * speed to <code>maxSpeed</code>.
     * <p>
     * 
     * This is used to create momentum speed (slowly increase/decrease the
     * sprite speed).
     * <p>
     * 
     * For example :
     * 
     * <pre>
     * Sprite s;
     * 
     * public void update(long elapsedTime) {
     *  // accelerate sprite speed by 0.002
     *  // and limit the maximum speed to 4
     *  // moving right
     *  s.addHorizontalSpeed(elapsedTime, 0.002, 4);
     *  // moving left
     *  s.addHorizontalSpeed(elapsedTime, -0.002, -4);
     *  // momentum stop
     *  s.addHorizontalSpeed(elapsedTime, (s.getHorizontalSpeed() &gt; 0) ? -0.002
     *          : 0.002, 0);
     * }
     * </pre>
     */
    public abstract void addHorizontalSpeed (long elapsedTime,
                                             double accel,
                                             double maxSpeed);


    /**
     * Accelerates sprite vertical speed by <code>accel</code> and limit the
     * speed to <code>maxSpeed</code>.
     * <p>
     * 
     * This is used to create momentum speed (slowly increase/decrease the
     * sprite speed).
     * <p>
     * 
     * For example :
     * 
     * <pre>
     * Sprite s;
     * 
     * public void update(long elapsedTime) {
     *  // accelerate sprite speed by 0.002
     *  // and limit the maximum speed to 4
     *  // moving down
     *  s.addVerticalSpeed(elapsedTime, 0.002, 4);
     *  // moving up
     *  s.addVerticalSpeed(elapsedTime, -0.002, -4);
     *  // momentum stop
     *  s.addVerticalSpeed(elapsedTime,
     *          (s.getVerticalSpeed() &gt; 0) ? -0.002 : 0.002, 0);
     * }
     * </pre>
     */
    public abstract void addVerticalSpeed (long elapsedTime,
                                           double accel,
                                           double maxSpeed);


    /**
     * Returns vertical speed of the sprite.
     * <p>
     * 
     * Positive means the sprite is moving to bottom, and negative means the
     * sprite is moving to top.
     */
    public abstract double getVerticalSpeed ();


    /**
     * Returns the distance of this sprite from the specified sprite.
     * <p>
     * 
     * Used this method to check whether the specified sprite is in this sprite
     * range area or not.
     * <p>
     * 
     * This method can be used for :
     * <ul>
     * <li>Determining sprite attack range.</li>
     * <li>Sprite aura that affecting surrounding unit.</li>
     * <li>Activating this sprite to chase player whenever the player come
     * closer to certain distance of this sprite.</li>
     * </ul>
     */
    public abstract double getDistance (BuildSprite other);

}
